#include "game_map.h"
#include "sdl_helper.h"

// init map
void game_map_init(struct game_map *m) {

	// background
	m->bg_tex = load_image("images/map_0.png");

	/* currently all platforms have fixed width
	 * height is only meant for visual reasons
	 * maybe it will be replaced with the texture's
	 * actual height
	 */
	m->grid_width = 72;
	m->grid_height = 36;

	// sample data
	m->tex_top = load_image("images/map_0_platform_top.png");
	m->tex_mid = load_image("images/map_0_platform_bottom.png");
	m->rect.x = 0;
	m->rect.y = 0;
	m->rect.w = m->grid_width;
	m->rect.h = m->grid_height;

	// give some height on the platforms for testing purposes
	int lowest = 0;
	for (int i = 0; i < 10; i++) {

		if (i < 5) {
			m->grid[i] = GAME_HEIGHT/2 -(GAME_HEIGHT/4) *i/10;
		}
		else {
			m->grid[i] = GAME_HEIGHT/4 +(GAME_HEIGHT/3) *i/10;
		}

		m->grid_actual[i] = m->grid[i];
		if (m->grid[i] > m->grid[lowest]) {
			lowest = i;
		}
	}

	// starting water level is on the first grid for now, should be lowest grid
	m->water_rect.x = 0;
	m->water_rect.y = m->water_actual = m->grid[lowest] +m->grid_width/2;
	m->water_rect.w = 640;
	m->water_rect.h = 0;
	m->water_delay = 0;
	m->water_speed = 1;

	m->offset_x = 0;
	m->offset_y = 0;

} // init

// all platforms on the map, keep approaching their targets constantly
void game_map_update(struct game_map *m) {

	// update grids and keep lowest
	int lowest = 0;
	int highest = 0;
	for (int i = 0; i < 10; i++) {
		m->grid[i] = m->grid[i] +(m->grid_actual[i] -m->grid[i]) *0.1;

		if (m->grid[i] > m->grid[lowest]) {
			lowest = i;
		}

		if (m->grid[i] < m->grid[highest]) {
			highest = i;
		}
	}

	// water keeps rising to an offset of the highest grid
	if (m->grid[highest] +24 +300 < m->water_actual) {
		m->water_actual = m->grid[highest] +24 +300;
	}
	else
	// water keeps rising to the lowest grid
	if (m->grid[lowest] +24 < m->water_actual) {
		m->water_actual = m->grid[lowest] +24;
	}
	else
	// or water keeps rising passively
	if (++m->water_delay >= 40) {
		m->water_delay = 0;
		m->water_actual -= m->water_speed;
		m->water_speed += 0.1;
	}
	m->water_rect.y = m->water_rect.y +(m->water_actual -m->water_rect.y) *0.1;
}

/* draw the map, one platform at a time
 */
void game_map_draw(struct game_map *m) {

	// background
	m->rect.w = 48;
	for (int x = m->offset_x %m->rect.w -m->rect.w; x < GAME_WIDTH ; x += m->rect.w)
	for (int y = m->offset_y %m->rect.h -m->rect.h; y < GAME_HEIGHT; y += m->rect.h) {
		m->rect.x = x;
		m->rect.y = y;
		SDL_RenderCopy(ren, m->bg_tex, NULL, &m->rect);
	}

	// draw platforms
	m->rect.w = m->grid_width;
	for (int i = 0; i < 10; i++) {

		// draw the top part
		m->rect.x = m->offset_x +i *m->grid_width;
		m->rect.y = m->offset_y +m->grid[i] -m->rect.h/2;
		SDL_RenderCopy(ren, m->tex_top, NULL, &m->rect);

		// draw the middle parts until it's below water
		m->rect.y += m->rect.h;
		m->rect.h *= 2;
		while (m->rect.y < m->water_rect.y +m->offset_y) {
			SDL_RenderCopy(ren, m->tex_mid, NULL, &m->rect);
			m->rect.y += m->rect.h;
		}
		m->rect.h /= 2;
	}

} // draw

/* draw front layer of the map,
 * this is meant to cover objects like players
 * currently used for the water, but could add more
 * things later
 */
void game_map_draw_front(struct game_map *m) {

	// draw water
	m->water_rect.y += m->offset_y;
	m->water_rect.h = 480 -m->water_rect.y;
	SDL_SetRenderDrawColor(ren, 80, 140, 200, 255);
	SDL_RenderFillRect(ren, &m->water_rect);
	m->water_rect.y -= m->offset_y;

}

// get ground height
int game_map_platform_y(struct game_map *m, int index) {
	if (index < 0 || index >= 10) return GAME_HEIGHT *2;
	return m->offset_y +m->grid[index];
}

// get ground index
int game_map_platform_id(struct game_map *m, int player_loc) {
	float grid_index = (player_loc -m->offset_x) /m->grid_width;
	if (player_loc < 0) grid_index = -1;
	if (grid_index < 0) grid_index = -1;
	else if (grid_index >= 10) grid_index = 10;
	return (int) grid_index;
}

int game_map_platform_x(struct game_map *m, int index) {
	return m->offset_x +index *m->grid_width;
}

void game_map_offset(struct game_map *s, int x, int y) {
	s->offset_x += x;
	s->offset_y += y;
}

void game_map_platform_rise(struct game_map *s, int index, int amount) {
	if (index < 0 || index > 9) return;
	s->grid_actual[index] += amount;
}

int game_map_water_y(struct game_map *s) {
	return s->water_actual +s->offset_y;
}

int game_map_platform_width(struct game_map *s) {
	return s->grid_width;
}

int game_map_platform_number(struct game_map *s) {
	return 10;
}
